#include "spring.h"
#include "vector.h"
#include "vector3d.h"
//
Matrix Spring::k_ = Matrix(6, 6); //return the local matrix of stiffness of the spring
Matrix Spring::c_ = Matrix(6, 6); //return local matrix of damping of the spring

Spring::Spring()
{
    id = 0;
    type = 0;
	lo = 0.0;
	lc = 0.0;
	ks = 0.0;
	kd = 0.0;
    color = Color(1, 0, 1, 1);
    selected = false;
}

Spring::Spring(int _id, unsigned int _t, int _begin, int _end) : id(_id), type(_t), particleBegin(_begin), particleEnd(_end), ks(0), kd(0)
{
    switch(type)
    {
        case STRUCTURAL_HORIZONTAL:
        case STRUCTURAL_VERTICAL:
        {
            color = Color (0.0, 1.0, 0.0, 1);
            break;
        }
        case SHEAR:
        {
            color = Color (0.0, 1.0, 1.0, 1);
            break;
        }
        case FLEXION:
        {
            color = Color (0.0, 0.0, 1.0, 1);
            break;
        }
    }

	lo = 0;

    selected = false;
}

Spring::Spring(int _id, unsigned int _t, Particle *_begin, Particle *_end, const Color &_c) : id(_id), type(_t), color(_c), ks(0), kd(0)
{
    particleBegin = _begin->getID();

    particleEnd = _end->getID();

	lo = getCurrentLength(_begin, _end);

    Spring::k_[0][0] = -ks;
    Spring::k_[1][1] = -ks;
    Spring::k_[2][2] = -ks;
    Spring::k_[3][3] = -ks;
    Spring::k_[4][4] = -ks;
    Spring::k_[5][5] = -ks;
    Spring::k_[0][3] = ks;
    Spring::k_[1][4] = ks;
    Spring::k_[2][5] = ks;
    Spring::k_[3][0] = ks;
    Spring::k_[4][1] = ks;
    Spring::k_[5][2] = ks;

    Spring::c_[0][0] = -kd;
    Spring::c_[1][1] = -kd;
    Spring::c_[2][2] = -kd;
    Spring::c_[3][3] = -kd;
    Spring::c_[4][4] = -kd;
    Spring::c_[5][5] = -kd;
    Spring::c_[0][3] = kd;
    Spring::c_[1][4] = kd;
    Spring::c_[2][5] = kd;
    Spring::c_[3][0] = kd;
    Spring::c_[4][1] = kd;
    Spring::c_[5][2] = kd;

    selected = false;
}

Spring::Spring(int _id, unsigned int _t, double _ks, double _kd, Particle *_begin, Particle *_end, const Color &_c) : id(_id), type(_t), color(_c), ks(_ks), kd(_kd)
{
    particleBegin = _begin->getID();

    particleEnd = _end->getID();

	lo = getCurrentLength(_begin, _end);

    Spring::k_[0][0] = -ks;
    Spring::k_[1][1] = -ks;
    Spring::k_[2][2] = -ks;
    Spring::k_[3][3] = -ks;
    Spring::k_[4][4] = -ks;
    Spring::k_[5][5] = -ks;
    Spring::k_[0][3] = ks;
    Spring::k_[1][4] = ks;
    Spring::k_[2][5] = ks;
    Spring::k_[3][0] = ks;
    Spring::k_[4][1] = ks;
    Spring::k_[5][2] = ks;

    Spring::c_[0][0] = -kd;
    Spring::c_[1][1] = -kd;
    Spring::c_[2][2] = -kd;
    Spring::c_[3][3] = -kd;
    Spring::c_[4][4] = -kd;
    Spring::c_[5][5] = -kd;
    Spring::c_[0][3] = kd;
    Spring::c_[1][4] = kd;
    Spring::c_[2][5] = kd;
    Spring::c_[3][0] = kd;
    Spring::c_[4][1] = kd;
    Spring::c_[5][2] = kd;

    selected = false;
}

Spring::~Spring()
{

}
//return the id of the spring
int Spring::getID() const
{
    return id;
}

//return the type of the spring
unsigned int Spring::getType() const
{
    return type;
}

//return the color of spring
Color Spring::getColor() const
{
    if(selected) return Color(1,0,0,1);
	return color;
}

//return the color of spring
const Color &Spring::getActualColor() const
{
	return color;
}

//change the color of the spring
void Spring::setColor(const Color &_c)
{
	color = _c;
}

//change both coefficients
void Spring::setKsAndKd(double _ks, double _kd){
    ks = _ks;
    kd = _kd;
}

//returns the coefficient of rigidity
double Spring::getKs() const{
	return ks;
}

//change the coefficient of rigidity
void Spring::setKs(double _k)
{
	ks = _k;
}

//returns the coefficient of damping
double Spring::getKd() const
{
	return kd;
}

//change the coefficient of damping
void Spring::setKd(double _k)
{
	kd = _k;
}
//return the initial particle
int Spring::getParticleBegin() const
{
	return particleBegin;
}

//return the end particle
int Spring::getParticleEnd() const
{
	return particleEnd;
}

//resting length
double Spring::getOriginalLength() const
{
	return lo;
}

//calculating the current lenght
double Spring::getCurrentLength(Particle *_begin, Particle *_end)
{
    lc = Vector(_begin->getPosition() - _end->getPosition()).length();
	return lc;
}
//calculating the current lenght
double Spring::getCurrentLength(Vector3D _beginPosition, Vector3D _endPosition)
{
    lc = Vector(_beginPosition - _endPosition).length();
    return lc;
}
//said spring is stretched or compressed
bool Spring::positiveDelta() const
{
	if(lc - lo > 0.0) return true; //houve alongamento
	return false; //compressão
}

//return local matrix of stiffness
void Spring::printK_() const
{
    k_.print();
}

//return local matrix damping
void Spring::printC_() const
{
    c_.print();
}

//return local matrix of stiffness of the spring
const Matrix& Spring::getK_() const
{
    return k_;
}

//return local matrix of damping of the spring
const Matrix& Spring::getC_() const
{
    return c_;
}

/** Modificar para ter densidade do tecido */
//updating the particle's mass
void Spring::addParticleMass(Particle *_m1, Particle *_m2)
{
    double w = (lo/(2.0)) * (5.0/100.0); //pegando 5%

    _m2->setMass(_m2->getMass() + w);
    _m1->setMass(_m1->getMass() + w);

}

//relaxed length of the spring
void Spring::relax()
{
    lc = lo;
}
